<template>
    <div class="container">
        <div class="chat-header">
            <div class="chat-box super-editor-flex super-editor-header">
                <div class="chat-logo-box super-editor-avatar">
                    <!-- <img :src="props.plugin.img" alt=""> -->
                    {{ props.plugin.logo }}
                </div>
                <div class="chat-info-box">
                    <div class="super-editor-flex">
                        <div class="chat-name">{{ props.plugin.name }}</div>
                        <div class="chat-model">{{ props.plugin.model }}</div>
                    </div>
                    <div class="chat-desc">{{ props.plugin.describe }}</div>
                </div>

            </div>
            <div class="super-editor-flex chat-box-right" v-if="props.readOnly === false">
                <div class="chat-config super-editor-button-box" @click="handleResize" v-show="false">
                        <PanelRightClose />
                </div>
                <div class="chat-config super-editor-button-box" @click="handleEdit">
                    <FilePenLine />
                </div>
            </div>
        </div>
        <el-row>
            <el-col :span="mainSpan">
                <div class="chat-msg-box">
                    <el-scrollbar class="scroll-bar" ref="scrollBarRef" height="">
                        <div v-for="(item, index) in msgList" :key="index" :class="getClass(item)">
                            <div class="msg-item-left" v-if="isLeft(item)">
                                <div class="super-editor-avatar">
                                    {{ props.plugin.logo }}
                                </div>
                                <div class="msg-item-text">
                                    <!-- <p class="msg-item-text-a">{{ item.msg }}</p> -->
                                    <div class="msg-item-text-a" v-html="getMdiText(item.msg)"></div>
                                </div>
                            </div>

                            <div class="msg-item-right" v-else>
                                <div class="msg-item-text">
                                    <!-- <p class="msg-item-text-a">{{ item.msg }}</p> -->
                                    <div class="msg-item-text-a" v-html="getMdiText(item.msg)"></div>
                                </div>
                                <div><img class="msg-item-right-img" :src="item.avatar" /></div>
                            </div>
                        </div>
                        <div class="msg-item-cleft" v-show="isStreamShow">
                            <div class="msg-item-left">
                                <div class="super-editor-avatar">
                                    {{ props.plugin.logo }}
                                </div>
                                <div class="msg-item-text custom-loading-svg">
                                    <!-- <p class="msg-item-text-a">{{ streamMsg }}</p> -->
                                    <div class="msg-item-text-a" v-html="getMdiText(streamMsg)"></div>
                                </div>
                            </div>
                        </div>
                    </el-scrollbar>
                    <div class="chat-footer">
                        <div class="chat-msg-tool-bar">
                            <div class="chat-msg-tool-bar-left">

                            </div>
                            <div class="chat-msg-tool-bar-right">

                            </div>
                        </div>
                        <!-- <div class="msg-tool-bar">
                            <el-button v-for=" plugin in chatPlugins" type="primary" @click="sendMsg(plugin)">{{ plugin.name
                            }}</el-button>
                        </div> -->
                        <el-input class="msg-input" v-model="userPrompt" :autosize="{ minRows: 3, maxRows: 3 }"
                            type="textarea" placeholder="请输入聊天内容" @keyup.enter.exact="sendMsg(plugin)" @keyup.shift.enter="lineEnter" resize="none" />
                        <div class="chat-mgs-action super-editor-flex-end">
                            <div>
                                <span class="chat-mgs-action-info">
                                    <CornerDownLeft :size="12" />发送/<ArrowBigUp :size="12"/><CornerDownLeft :size="12"/>换行
                                </span>
                            </div>
                            <div>
                                <el-button type="primary" color="#222222" @click="sendMsg(plugin)">发送</el-button>
                            </div>
                        </div>
                    </div>
                </div>
            </el-col>
            <el-col :span="configSpan">
                <div class="chat-plugin-config">
                    <Topic v-model:plugin="props.plugin" />
                </div>
            </el-col>
        </el-row>
    </div>
</template>

<script setup>
import { ref, watch, onUpdated, inject, computed } from 'vue'
import { chat } from '@/api/plugin'

import MarkdownIt from 'markdown-it'
import mdKatex from '@traptitech/markdown-it-katex'
import hljs from 'highlight.js';
import PluginConfig from './PluginConfig.vue';
import Topic from './Topic.vue';
import { CornerDownLeft, ArrowBigUp,PanelRightClose,FilePenLine } from 'lucide-vue-next';

//如下代码给消息加上markdown语法支持
const mdi = new MarkdownIt({
    linkify: true,
    highlight(code, language) {
        const validLang = !!(language && hljs.getLanguage(language))
        if (validLang) {
            const lang = language ?? ''
            return highlightBlock(hljs.highlight(lang, code, true).value, lang)
        }
        return highlightBlock(hljs.highlightAuto(code).value, '')
    }
})
mdi.use(mdKatex, { blockClass: 'katexmath-block rounded-md p-[10px]', errorColor: ' #cc0000' })

function highlightBlock(str, lang) {
    return `<pre class="pre-code-box"><div class="pre-code-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">复制代码</span></div><div class="pre-code"><code class="hljs code-block-body ${lang}">${str}</code></div></pre>`
}

const getMdiText = (value) => {
    return mdi.render(value)
}

const props = defineProps({
    chatContent: {
        type: String,
        default: ''
    },
    plugin: {
        type: Object,
        default: { name: "全能选手", id: "1", prompt: "", model: 'gpt-3.5', describe: '全能，什么都知道' },
    },
    readOnly: {
        type: Boolean,
        default: false
    }
})

const emits = defineEmits(['update:chatContent', 'update:plugin'])

const chatContent = computed({
    get() {
        return props.chatContent
    },
    set(value) {
        emits('update:chatContent', value)
    }
})

const chatPlugins = ref([{ name: "总结", id: "id1", prompt: "帮我总结下这篇文章" }, { name: "脑图", id: "id2", prompt: "" }, {
    name: "翻译", id: "id3", prompt: `你现在是一位专业的中英文翻译家，擅长将中文翻译成通俗易懂的英文。在输出生成结果时，请在输出段落时，同时输出中文和英文对照。参考示例：

输入：

生命短暂，时光飞逝；江河轻阵，船只远行。

我们约若眨眼间即逝的时光；我们的相遇如同天际与江水的融合。

输出：
生命短暂，时光飞逝；江河轻阵，船只远行。
Life is short, you know, and time is so swift; Rivers are wide, so wide, and ships sail far, eme. 

我们约若眨眼间即逝的时光；我们的相遇如同天际与江水的融合。
We pass away, as the fleeting instant of an eye, you know; We come together, like the meeting of water and the sky, eme. 


现在请翻译以下英文为中英文双语对照：`}])

const msgList = ref([])

watch(() => props.chatContent, (n, v) => {
    let msg = { msg: '您好，有什么可以帮您的？', time: '', name: '', avatar: '', userId: '123456' }
    msg.msg = props.chatContent
    msg.time = new Date().toLocaleTimeString()
    msg.name = 'admin'
    msg.avatar = props.plugin.img
    msg.userId = '123456'
    userPrompt.value = ''
})

watch(() => props.plugin, (n, o) => {
    const helloMessage = { msg: props.plugin.describe, time: '', name: '', avatar: props.plugin.img, userId: '123456' }
    msgList.value = [helloMessage]
    initLayout()
})


const scrollBarRef = ref(null)
const userPrompt = ref('')

const streamMsg = ref('')
const isStreamShow = ref(false)

const sendMsg = (plugin) => {

    if (userPrompt.value.trim() === '') return
    let msg = { msg: '您好，有什么可以帮您的？', time: '', name: '', avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png', userId: '123456' }
    msg.msg = userPrompt.value
    msg.time = new Date().toLocaleTimeString()
    msg.name = 'admin'
    msg.avatar = 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
    msg.userId = '1234567'
    msgList.value.push(msg)
    scrollBarRef.value.wrapRef.scrollTop = scrollBarRef.value.wrapRef.scrollHeight
    userPrompt.value = ''

    chat(msg.msg, props.plugin.id).then(async (reader) => {
        const textDecoder = new TextDecoder();
        let result = true;
        let output = "";
        let pluginMsg = { msg: '', time: '', name: '', avatar: props.plugin.img, userId: '123456' }
        pluginMsg.time = new Date().toLocaleTimeString()
        pluginMsg.name = 'admin'
        pluginMsg.avatar = props.plugin.img
        pluginMsg.userId = '123456'

        isStreamShow.value = true
        while (result) {
            const { done, value } = await reader.read();
            if (done) {
                result = false;
                break;
            }
            const chunkText = textDecoder.decode(value);
            pluginMsg.msg = pluginMsg.msg + chunkText
            streamMsg.value = streamMsg.value + chunkText
            scrollBarRef.value.wrapRef.scrollTop = scrollBarRef.value.wrapRef.scrollHeight

        }
        streamMsg.value = ''
        isStreamShow.value = false
        msgList.value.push(pluginMsg)
    })

}

const lineEnter = ()=>{
    userPrompt.value = userPrompt.value + '\n'
}

const isLeft = (item) => {
    return item.userId == '123456'
}

const getClass = (item) => {
    if (isLeft(item)) return 'msg-item-cleft'
    return 'msg-item-cright'
}

onUpdated(() => {
    // 在数据更新之后将滚动条滚动到底部
    scrollBarRef.value.wrapRef.scrollTop = scrollBarRef.value.wrapRef.scrollHeight
})

//如下代码控制布局以及是否显示右上角的按钮
const mainSpan = ref(24)
const configSpan = ref(0)

if (props.readOnly) {
    mainSpan.value = 24
    configSpan.value = 0
}

const handleResize = () => {
    if (configSpan.value > 0) {
        mainSpan.value = 24
        configSpan.value = 0
    } else {
        mainSpan.value = 16
        configSpan.value = 8
    }
}

const initLayout = () => {
    mainSpan.value = 24
    configSpan.value = 0
}

const userAction = inject('userAction')
const handleEdit = () => {
    userAction(props.plugin, 'edit')
}

</script>

<style scoped>
.container {
    /* height: 100vh; */
    border-left: 1px solid #ccc;
    border-right: 1px solid #ccc;
    /* background-color: #F3F3F3; */
}

.chat-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid #ccc;
    height: var(--supereditor-header-height);
}

.chat-box {
    padding: 0 10px;
}

.chat-box-right {
    margin-right: 10px;
}

.chat-model {
    color: #666666;
    padding: 5px 10px;
    margin-left: 0px;
    /* background: #000; */
    background: rgba(0, 0, 0, 0.06);
    border: 4px;
    font-size: 12px;
}

.chat-info-box {
    margin-left: 10px;
}

.chat-desc {
    font-size: 12px;
    color: #080808;
    padding-top: 5px;
    
}

.chat-name {
    font-weight: bold;
    padding-right: 10px;
}

.chat-config {
    /* padding-right: 20px; */
}

.chat-msg-box {
    border-right: 1px solid #ccc;
}

.scroll-bar {
    height: calc(100vh - var(--supereditor-header-height) - 150px);
}


.msg-item-cleft {
    display: flex;
    align-items: center;
    justify-content: start;
    margin: 10px;
    text-align: center;
    border-radius: 4px;
}

.msg-item-cright {
    display: flex;
    align-items: center;
    justify-content: end;

    margin: 10px;
    text-align: center;
    border-radius: 4px;
}

.msg-item-left {
    padding-right: 100px;
    display: flex;
    width: 100vw - 100px;
}

.msg-item-left-img {
    width: 40px;
    height: 40px;
}

.msg-item-left-text {
    background-size: cover;
    border-radius: 20px;
    background-color: var(--supereditor-primary-color);
}

.msg-item-right {
    padding-left: 100px;
    display: flex;
    justify-content: end;
    width: 100vw - 100px;
}

.msg-item-right-img {
    width: 40px;
    height: 40px;
}

.msg-item-text {
    background-size: cover;
    border-radius: 5px;
    background-color: var(--supereditor-primary-color);
    vertical-align: middle;
    margin: 0 10px;
    min-height: 30px;
    padding: 14px 10px;
    padding-bottom: 0;
    font-size: 16px;
    color: #0F170A;
    /* line-height: 30px; */
    /* display: flex;
    justify-content: center;
    flex-direction: column; */
}

.msg-item-text-a {
    text-align: left;
    vertical-align: middle;
    /* background-color: pink; */
}

.chat-footer {
    height: 150px;
    padding: 10px;
    border-top: 1px solid var(--supereditor-border-color);
}

.msg-tool-bar {
    /* border-top: 1px solid var(--supereditor-primary-color); */
    /* padding: 0 10px; */
}

::v-deep .msg-input .el-textarea__inner{
    border:0px;
    box-shadow: 0 0 0 0px var(--el-input-border-color,var(--el-border-color)) inset;
}

.chat-mgs-action {
    padding: 5px 0;
    text-align: right;
    gap: 8px;
}

.chat-mgs-action-info {
    font-size: 12px;
    height: 20px;
}</style>
